/*
 * CC3Mesh.m
 *
 * cocos3d 0.6.1
 * Author: Bill Hollings
 * Copyright (c) 2010-2011 The Brenwill Workshop Ltd. All rights reserved.
 * http://www.brenwill.com
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 * 
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 *
 * http://en.wikipedia.org/wiki/MIT_License
 * 
 * See header file CC3Mesh.h for full API documentation.
 */

#include "CC3Mesh.h"

CC3Mesh::CC3Mesh()
{
}

CC3Mesh::~CC3Mesh()
{
}

bool CC3Mesh::getHasNormals()
{
	return false;
}

bool CC3Mesh::getHasColors()
{
	return false;
}

CC3BoundingBox CC3Mesh::getBoundingBox()
{
	return kCC3BoundingBoxNull;
}

CC3Mesh* CC3Mesh::mesh()
{
	CC3Mesh* pMesh = new CC3Mesh;
	if (pMesh) 
	{
		pMesh->autorelease();
	}
	
	return pMesh;
}

CC3Mesh* CC3Mesh::meshWithTag(GLuint aTag)
{
	CC3Mesh* pMesh = new CC3Mesh;
	if (pMesh) 
	{
		pMesh->initWithTag(aTag);
		pMesh->autorelease();
	}
	
	return pMesh;
}

CC3Mesh* CC3Mesh::meshWithName(const char* aName)
{
	CC3Mesh* pMesh = new CC3Mesh;
	if (pMesh) 
	{
		pMesh->initWithName(aName);
		pMesh->autorelease();
	}
	
	return pMesh;
}

CC3Mesh* CC3Mesh::meshWithTag(GLuint aTag, const char* aName)
{
	CC3Mesh* pMesh = new CC3Mesh;
	if (pMesh) 
	{
		pMesh->initWithTag(aTag, aName);
		pMesh->autorelease();
	}
	
	return pMesh;
}

void CC3Mesh::createGLBuffers()
{
}

void CC3Mesh::deleteGLBuffers()
{
}

void CC3Mesh::releaseRedundantData()
{
}

void CC3Mesh::retainVertexLocations()
{
}

void CC3Mesh::retainVertexNormals()
{
}

void CC3Mesh::retainVertexColors()
{
}

void CC3Mesh::retainVertexTextureCoordinates()
{
}

void CC3Mesh::retainVertexIndices()
{
}

void CC3Mesh::doNotBufferVertexLocations()
{
}

void CC3Mesh::doNotBufferVertexColors()
{
}

void CC3Mesh::doNotBufferVertexNormals()
{
}

void CC3Mesh::doNotBufferVertexIndices()
{
}

void CC3Mesh::doNotBufferVertexTextureCoordinates()
{
}

void CC3Mesh::alignWithTexturesIn(CC3Material* aMaterial)
{
}

void CC3Mesh::alignWithInvertedTexturesIn(CC3Material* aMaterial)
{
}

cocos2d::CCRect CC3Mesh::getTextureRectangle()
{
	return cocos2d::CCRectZero;
}

void CC3Mesh::setTextureRectangle(cocos2d::CCRect newValue)
{
}

cocos2d::CCRect CC3Mesh::textureRectangleForTextureUnit(GLuint texUnit)
{
	return cocos2d::CCRectZero;
}

void CC3Mesh::setTextureRectangle(cocos2d::CCRect aRect, GLuint texUnit)
{
}

void CC3Mesh::drawWithVisitor(CC3NodeDrawingVisitor* visitor)
{
	if (getSwitchingMesh()) 
	{
		bindGLWithVisitor(visitor);
	} 
	else 
	{
		//LogTrace(@"Reusing currently bound %@", self);
	}
	
	drawVerticesWithVisitor(visitor);
}

static GLuint currentMeshTag = 0;

bool CC3Mesh::getSwitchingMesh()
{
	bool shouldSwitch = (currentMeshTag != tag);
	currentMeshTag = tag;		// Set anyway - either it changes or it doesn't.
	return shouldSwitch;
}

void CC3Mesh::bindGLWithVisitor(CC3NodeDrawingVisitor* visitor)
{
}

void CC3Mesh::drawVerticesWithVisitor(CC3NodeDrawingVisitor* visitor)
{
}

CC3NodeBoundingVolume* CC3Mesh::getDefaultBoundingVolume()
{
	return NULL;
}

CC3Vector CC3Mesh::vertexLocationAt(GLsizei index)
{
	return kCC3VectorZero;
}

void CC3Mesh::setVertexLocation(CC3Vector aLocation, GLsizei index)
{
}

CC3Vector CC3Mesh::vertexNormalAt(GLsizei index)
{
	return kCC3VectorZero;
}

void CC3Mesh::setVertexNormal(CC3Vector aNormal, GLsizei index)
{
}

cocos2d::ccColor4F CC3Mesh::vertexColor4FAt(GLsizei index)
{
	return kCCC4FBlackTransparent;
}

void CC3Mesh::setVertexColor4F(cocos2d::ccColor4F aColor, GLsizei index)
{
}

cocos2d::ccColor4B CC3Mesh::vertexColor4BAt(GLsizei index)
{
	return cocos2d::ccc4( 0, 0, 0, 0 );
}

void CC3Mesh::setVertexColor4B(cocos2d::ccColor4B aColor, GLsizei index)
{
}

cocos2d::ccTex2F CC3Mesh::vertexTexCoord2FAt(GLsizei index, GLuint texUnit)
{
	return cocos2d::tex2( 0.0, 0.0 );
}

void CC3Mesh::setVertexTexCoord2F(cocos2d::ccTex2F aTex2F, GLsizei index, GLuint texUnit)
{
}

cocos2d::ccTex2F CC3Mesh::vertexTexCoord2FAt(GLsizei index)
{
	return vertexTexCoord2FAt(index, 0);
}

void CC3Mesh::setVertexTexCoord2F(cocos2d::ccTex2F aTex2F, GLsizei index)
{
	setVertexTexCoord2F(aTex2F, index, 0);
}

GLushort CC3Mesh::vertexIndexAt(GLsizei index)
{
	return 0;
}

void CC3Mesh::setVertexIndex(GLushort vertexIndex, GLsizei index)
{
}

void CC3Mesh::resetSwitching()
{
	currentMeshTag = 0;
}

//@interface CC3Mesh (TemplateMethods)
//-(void) bindGLWithVisitor: (CC3NodeDrawingVisitor*) visitor;
//-(void) drawVerticesWithVisitor: (CC3NodeDrawingVisitor*) visitor;
//-(BOOL) switchingMesh;
//@end
//
//@implementation CC3Mesh
//
//-(BOOL) hasNormals {
//	return NO;
//}
//
//-(BOOL) hasColors {
//	return NO;
//}
//
//-(CC3BoundingBox) boundingBox {
//	return kCC3BoundingBoxNull;
//}
//
//#pragma mark Allocation and initialization
//
//+(id) mesh {
//	return [[[self alloc] init] autorelease];
//}
//
//+(id) meshWithTag: (GLuint) aTag {
//	return [[[self alloc] initWithTag: aTag] autorelease];
//}
//
//+(id) meshWithName: (NSString*) aName {
//	return [[[self alloc] initWithName: aName] autorelease];
//}
//
//+(id) meshWithTag: (GLuint) aTag withName: (NSString*) aName {
//	return [[[self alloc] initWithTag: aTag withName: aName] autorelease];
//}
//
//-(void) createGLBuffers {}
//
//-(void) deleteGLBuffers {}
//
//-(void) releaseRedundantData {}
//
//-(void) retainVertexLocations {}
//
//-(void) retainVertexNormals {}
//
//-(void) retainVertexColors {}
//
//-(void) retainVertexTextureCoordinates {}
//
//-(void) retainVertexIndices {}
//
//-(void) doNotBufferVertexLocations {}
//
//-(void) doNotBufferVertexNormals {}
//
//-(void) doNotBufferVertexColors {}
//
//-(void) doNotBufferVertexTextureCoordinates {}
//
//-(void) doNotBufferVertexIndices {}
//
//-(void) alignWithTexturesIn: (CC3Material*) aMaterial {}
//
//-(void) alignWithInvertedTexturesIn: (CC3Material*) aMaterial {}
//
//-(CGRect) textureRectangle { return CGRectNull; }
//
//-(void) setTextureRectangle: (CGRect) aRect {}
//
//-(CGRect) textureRectangleForTextureUnit: (GLuint) texUnit { return CGRectNull; }
//
//-(void) setTextureRectangle: (CGRect) aRect forTextureUnit: (GLuint) texUnit {}
//
//
//#pragma mark Tag allocation
//
//// Class variable tracking the most recent tag value assigned for CC3MeshModels.
//// This class variable is automatically incremented whenever the method nextTag is called.
//static GLuint lastAssignedMeshTag;
//
//-(GLuint) nextTag {
//	return ++lastAssignedMeshTag;
//}
//
//+(void) resetTagAllocation {
//	lastAssignedMeshTag = 0;
//}
//
//
//#pragma mark Drawing
//
//-(void) drawWithVisitor: (CC3NodeDrawingVisitor*) visitor {
//	if (self.switchingMesh) {
//		[self bindGLWithVisitor: visitor];
//	} else {
//		LogTrace(@"Reusing currently bound %@", self);
//	}
//	[self drawVerticesWithVisitor: visitor];
//}
//
///**
// * Template method that binds the mesh arrays to the GL engine prior to drawing.
// * The specified visitor encapsulates the frustum of the currently active camera,
// * and certain drawing options.
// *
// * This method does not create GL buffers, which are created with the createGLBuffers method.
// * This method binds the buffer or data pointers to the GL engine, prior to each draw call.
// */
//-(void) bindGLWithVisitor: (CC3NodeDrawingVisitor*) visitor {}
//
///** 
// * Draws the mesh vertices to the GL engine.
// * Default implementation does nothing. Subclasses will override.
// */
//-(void) drawVerticesWithVisitor: (CC3NodeDrawingVisitor*) visitor {}
//
//-(CC3NodeBoundingVolume*) defaultBoundingVolume {
//	return nil;
//}
//
//
//#pragma mark Accessing vertex data
//
//-(CC3Vector) vertexLocationAt: (GLsizei) index { return kCC3VectorZero; }
//
//-(void) setVertexLocation: (CC3Vector) aLocation at: (GLsizei) index {}
//
//-(CC3Vector) vertexNormalAt: (GLsizei) index { return kCC3VectorZero; }
//
//-(void) setVertexNormal: (CC3Vector) aNormal at: (GLsizei) index {}
//
//-(ccColor4F) vertexColor4FAt: (GLsizei) index { return kCCC4FBlackTransparent; }
//
//-(void) setVertexColor4F: (ccColor4F) aColor at: (GLsizei) index {}
//
//-(ccColor4B) vertexColor4BAt: (GLsizei) index { return (ccColor4B){ 0, 0, 0, 0 }; }
//
//-(void) setVertexColor4B: (ccColor4B) aColor at: (GLsizei) index {}
//
//-(ccTex2F) vertexTexCoord2FAt: (GLsizei) index forTextureUnit: (GLuint) texUnit {
//	return (ccTex2F){ 0.0, 0.0 };
//}
//
//-(void) setVertexTexCoord2F: (ccTex2F) aTex2F at: (GLsizei) index forTextureUnit: (GLuint) texUnit {}
//
//-(ccTex2F) vertexTexCoord2FAt: (GLsizei) index {
//	return [self vertexTexCoord2FAt: index forTextureUnit: 0];
//}
//
//-(void) setVertexTexCoord2F: (ccTex2F) aTex2F at: (GLsizei) index {
//	[self setVertexTexCoord2F: aTex2F at: index forTextureUnit: 0];
//}
//
//-(GLushort) vertexIndexAt: (GLsizei) index { return 0; }
//
//-(void) setVertexIndex: (GLushort) vertexIndex at: (GLsizei) index {}
//
//
//#pragma mark Mesh context switching
//
//// The tag of the mesh that was most recently drawn to the GL engine.
//// The GL engine is only updated when a mesh with a different tag is presented.
//// This allows for optimization by ordering the drawing of objects so that objects with
//// the same mesh are drawn together, to minimize context switching within the GL engine.
//static GLuint currentMeshTag = 0;
//
///**
// * Returns whether this mesh is different than the mesh that was most recently
// * drawn to the GL engine. To improve performance, meshes are only bound if they need to be.
// *
// * If appropriate, the application can arrange CC3MeshNodes in the CC3World so that nodes
// * using the same mesh are drawn together, to minimize the number of mesh binding
// * changes in the GL engine.
// *
// * This method is invoked automatically by the draw method to test whether this mesh needs
// * to be bound to the GL engine before drawing.
// */
//-(BOOL) switchingMesh {
//	BOOL shouldSwitch = currentMeshTag != tag;
//	currentMeshTag = tag;		// Set anyway - either it changes or it doesn't.
//	return shouldSwitch;
//}
//
//+(void) resetSwitching {
//	currentMeshTag = 0;
//}
//
//@end
//
//
//#pragma mark -
//#pragma mark Deprecated CC3MeshModel
//
//@implementation CC3MeshModel
//@end
